using System;
using System.Threading;
using System.IO.Ports;
using System.Text;

#if !PC
    using Microsoft.SPOT.Hardware;
#endif

namespace codebase
{
    public class FourDSPE
    {
        #region Declarations

#if !PC
        private OutputPort ro;
#endif

#if PICASO
        public event TouchDownHandler TouchDownEvent;
        public event TouchUpHandler TouchUpEvent;
        public event TouchMoveHandler TouchMoveEvent;
#endif

        private SerialPort sr;
        private FourDSerial fsr;

#if PICASO
        public int Width = 240;
        public int Height = 320;
#else
        public int Width = 128;
        public int Height = 128;
#endif

        private int _charWidth = 8;
        private int _charHeight = 8;

        public int WidthInChars = 0;
        public int HeightInChars = 0;
        public int CharWidth = 8;
        public int CharHeight = 8;
        public int CharWidthMultiplier = 1;
        public int CharHeightMultiplier = 1;
        #endregion

        #region General

        public int GetResponsePICASO()
        {
#if PICASO
            return fsr.getResponse();
#else
            return fsr.sendAndGetACK();
#endif
        }

        public void Reset()
        {
#if !PC
            ro.Write(false);
            Thread.Sleep(10);
            ro.Write(true);
            Thread.Sleep(10);
#else
            sr.RtsEnable = true;
            sr.DtrEnable = true;
            Thread.Sleep(10);
            sr.DtrEnable = false;
            sr.RtsEnable = false;
            Thread.Sleep(10);
#endif
        }

        public void ChangeBaudRate(int rate)
        {
            Thread.Sleep((int)FOURD.BAUDRATEDELAY);
            sr.Close();
            sr.BaudRate = rate;
            sr.Open();
        }

        string _Port;
#if !PC
        public void Initialize(string Port, int Baud, Cpu.Pin pin)
        {
            if (ro == null) ro = new OutputPort(pin, true);
#else
        public void Initialize(string Port, int Baud)
        {
#endif            
            _Port = Port;
            if (sr == null) sr = new SerialPort(_Port, Baud, Parity.None, 8, StopBits.One);
            if (!sr.IsOpen) sr.Open();

            Reset();

            Thread.Sleep((int)SPE.INITDELAYMS);

            fsr = new FourDSerial(sr);

            Thread.Sleep((int)SPE.INITDELAYMS);

            _charWidth = CharacterWidth('a');
            _charHeight = CharacterHeight('a');

            CharWidth = _charWidth;
            CharHeight = _charHeight;

            WidthInChars = Width / CharWidth;
            HeightInChars = Height / CharHeight;

#if PICASO
            lastTouchUpdate = DateTime.Now.Ticks / 10000;
#endif

            return;
        }

        #endregion

        #region Text

        public int SetFont(int id)
        {
            fsr.sendByte((byte)SPE.SETFONT_1);
            fsr.sendByte((byte)SPE.SETFONT_2);

            fsr.sendByte((byte)(id >> 8));
            fsr.sendByte((byte)(id & 0xFF));

            int ret = GetResponsePICASO();

            _charWidth = CharacterWidth('a');
            _charHeight = CharacterHeight('a');

            CharWidth = _charWidth;
            CharHeight = _charHeight;

            return ret;
        }

        public int CharacterWidth(char character)
        {
            fsr.sendByte((byte)SPE.CHARACTERWIDTH_1);
            fsr.sendByte((byte)SPE.CHARACTERWIDTH_2);

            fsr.sendByte((byte)character);

            return fsr.getResponse();
        }

        public int CharacterHeight(char character)
        {
            fsr.sendByte((byte)SPE.CHARACTERHEIGHT_1);
            fsr.sendByte((byte)SPE.CHARACTERHEIGHT_2);

            fsr.sendByte((byte)character);

            return fsr.getResponse();
        }

        public int MoveCursor(int line, int column)
        {
            fsr.sendByte((byte)SPE.MOVECURSOR_1);
            fsr.sendByte((byte)SPE.MOVECURSOR_2);

            fsr.sendByte((byte)(line >> 8));
            fsr.sendByte((byte)(line & 0xFF));
            fsr.sendByte((byte)(column >> 8));
            fsr.sendByte((byte)(column & 0xFF));

            return fsr.sendAndGetACK();
        }

        public int TextForeGroundColor(int color)
        {
            fsr.sendByte((byte)SPE.TEXTFOREGROUNDCOLOR_1);
            fsr.sendByte((byte)SPE.TEXTFOREGROUNDCOLOR_2);

            fsr.sendByte((byte)(color >> 8));
            fsr.sendByte((byte)(color & 0xFF));

            return GetResponsePICASO();
        }

        public int TextBackGroundColor(int color)
        {
            fsr.sendByte((byte)SPE.TEXTBACKGROUNDCOLOR_1);
            fsr.sendByte((byte)SPE.TEXTBACKGROUNDCOLOR_2);

            fsr.sendByte((byte)(color >> 8));
            fsr.sendByte((byte)(color & 0xFF));

            return GetResponsePICASO();
        }

        public int PutString(string text)
        {
            if (text == "") return (int)FOURD.NAK;

            byte[] textBytes = Encoding.UTF8.GetBytes(text);
            fsr.sendByte((byte)SPE.PUTSTRING_1);
            fsr.sendByte((byte)SPE.PUTSTRING_2);

            foreach (byte bt in textBytes)
            {
                fsr.sendByte(bt);
            }

            fsr.sendByte(0x00);

            return GetResponsePICASO();
        }

        public int TextWidth(int multiplier)
        {
            fsr.sendByte((byte)SPE.TEXTWIDTH_1);
            fsr.sendByte((byte)SPE.TEXTWIDTH_2);

            fsr.sendByte((byte)(multiplier >> 8));
            fsr.sendByte((byte)(multiplier & 0xFF));

            CharWidthMultiplier = multiplier;
            CharWidth = _charWidth * multiplier;

            return GetResponsePICASO();
        }

        public int TextHeight(int multiplier)
        {
            fsr.sendByte((byte)SPE.TEXTHEIGHT_1);
            fsr.sendByte((byte)SPE.TEXTHEIGHT_2);

            fsr.sendByte((byte)(multiplier >> 8));
            fsr.sendByte((byte)(multiplier & 0xFF));

            CharHeightMultiplier = multiplier;
            CharHeight = _charHeight * multiplier;

            return GetResponsePICASO();
        }

        public int TextOpacity(int mode)
        {
            fsr.sendByte((byte)SPE.TEXTOPACITY_1);
            fsr.sendByte((byte)SPE.TEXTOPACITY_2);

            fsr.sendByte((byte)(mode >> 8));
            fsr.sendByte((byte)(mode & 0xFF));

            return GetResponsePICASO();
        }

        #endregion

        #region Graphics

        public int BackgroundColor(int color)
        {
            fsr.sendByte((byte)SPE.BACKGROUNDCOLOR_1);
            fsr.sendByte((byte)SPE.BACKGROUNDCOLOR_2);
            fsr.sendByte((byte)(color >> 8));
            fsr.sendByte((byte)(color & 0xFF));

            return GetResponsePICASO();
        }

        public int ChangeColor(int oldcolor, int newcolor)
        {
            fsr.sendByte((byte)SPE.CHANGECOLOR_1);
            fsr.sendByte((byte)SPE.CHANGECOLOR_2);
            fsr.sendByte((byte)(oldcolor >> 8));
            fsr.sendByte((byte)(oldcolor & 0xFF));
            fsr.sendByte((byte)(newcolor >> 8));
            fsr.sendByte((byte)(newcolor & 0xFF));

            return fsr.sendAndGetACK();
        }

        public int OutlineColor(int color)
        {
            fsr.sendByte((byte)SPE.OUTLINECOLOR_1);
            fsr.sendByte((byte)SPE.OUTLINECOLOR_2);
            fsr.sendByte((byte)(color >> 8));
            fsr.sendByte((byte)(color & 0xFF));

            return GetResponsePICASO();
        }

        public int Contrast(int contrast)
        {
            fsr.sendByte((byte)SPE.CONTRAST_1);
            fsr.sendByte((byte)SPE.CONTRAST_2);
            fsr.sendByte((byte)(contrast >> 8));
            fsr.sendByte((byte)(contrast & 0xFF));

            return GetResponsePICASO();
        }

        public int FrameDelay(int Msec)
        {
            fsr.sendByte((byte)SPE.FRAMEDELAY_1);
            fsr.sendByte((byte)SPE.FRAMEDELAY_2);
            fsr.sendByte((byte)(Msec >> 8));
            fsr.sendByte((byte)(Msec & 0xFF));

            return GetResponsePICASO();
        }

        public int LinePattern(int pattern)
        {
            fsr.sendByte((byte)SPE.LINEPATTERN_1);
            fsr.sendByte((byte)SPE.LINEPATTERN_2);
            fsr.sendByte((byte)(pattern >> 8));
            fsr.sendByte((byte)(pattern & 0xFF));

            return GetResponsePICASO();
        }

        public int ScreenMode(int mode)
        {
            fsr.sendByte((byte)SPE.SCREENMODE_1);
            fsr.sendByte((byte)SPE.SCREENMODE_2);
            fsr.sendByte((byte)(mode >> 8));
            fsr.sendByte((byte)(mode & 0xFF));

            return GetResponsePICASO();
        }

        public int Transparency(int mode)
        {
#if PICASO
            fsr.sendByte((byte)SPE.TRANSPARENCY_1);
            fsr.sendByte((byte)SPE.TRANSPARENCY_2);
            fsr.sendByte((byte)(mode >> 8));
            fsr.sendByte((byte)(mode & 0xFF));

            return GetResponsePICASO();
#else
            return (int)FOURD.NAK;
#endif
        }

        public int TransparentColor(int color)
        {
#if PICASO
            fsr.sendByte((byte)SPE.TRANSPARENTCOLOR_1);
            fsr.sendByte((byte)SPE.TRANSPARENTCOLOR_2);
            fsr.sendByte((byte)(color >> 8));
            fsr.sendByte((byte)(color & 0xFF));

            return GetResponsePICASO();
#else
            return (int)FOURD.NAK;
#endif
        }

        public int SetGraphicsParameters(int function, int value)
        {
            fsr.sendByte((byte)SPE.SETGRAPHICSPARAMETERS_1);
            fsr.sendByte((byte)SPE.SETGRAPHICSPARAMETERS_2);

            fsr.sendByte((byte)(function >> 8));
            fsr.sendByte((byte)(function & 0xFF));
            fsr.sendByte((byte)(value >> 8));
            fsr.sendByte((byte)(value & 0xFF));

            return fsr.sendAndGetACK();
        }

        public int Clear() 
        {
            fsr.sendByte((byte)SPE.CLEAR_1);
            fsr.sendByte((byte)SPE.CLEAR_2);

            return fsr.sendAndGetACK();
        }

        public int DrawCircle(int x, int y, int rad, int color)
        {
            fsr.sendByte((byte)SPE.DRAWCIRCLE_1);
            fsr.sendByte((byte)SPE.DRAWCIRCLE_2);

            fsr.sendByte((byte)(x >> 8));
            fsr.sendByte((byte)(x & 0xFF));
            fsr.sendByte((byte)(y >> 8));
            fsr.sendByte((byte)(y & 0xFF));
            fsr.sendByte((byte)(rad >> 8));
            fsr.sendByte((byte)(rad & 0xFF));
            fsr.sendByte((byte)(color >> 8));
            fsr.sendByte((byte)(color & 0xFF));

            return fsr.sendAndGetACK();
        }

        public int DrawFilledCircle(int x, int y, int rad, int color)
        {
            fsr.sendByte((byte)SPE.DRAWFILLEDCIRCLE_1);
            fsr.sendByte((byte)SPE.DRAWFILLEDCIRCLE_2);

            fsr.sendByte((byte)(x >> 8));
            fsr.sendByte((byte)(x & 0xFF));
            fsr.sendByte((byte)(y >> 8));
            fsr.sendByte((byte)(y & 0xFF));
            fsr.sendByte((byte)(rad >> 8));
            fsr.sendByte((byte)(rad & 0xFF));
            fsr.sendByte((byte)(color >> 8));
            fsr.sendByte((byte)(color & 0xFF));

            return fsr.sendAndGetACK();
        }

        public int DrawLine(int x, int y, int x2, int y2, int color)
        {
            fsr.sendByte((byte)SPE.DRAWLINE_1);
            fsr.sendByte((byte)SPE.DRAWLINE_2);

            fsr.sendByte((byte)(x >> 8));
            fsr.sendByte((byte)(x & 0xFF));
            fsr.sendByte((byte)(y >> 8));
            fsr.sendByte((byte)(y & 0xFF));
            fsr.sendByte((byte)(x2 >> 8));
            fsr.sendByte((byte)(x2 & 0xFF));
            fsr.sendByte((byte)(y2 >> 8));
            fsr.sendByte((byte)(y2 & 0xFF));
            fsr.sendByte((byte)(color >> 8));
            fsr.sendByte((byte)(color & 0xFF));

            return fsr.sendAndGetACK();
        }

        public int DrawRectangle(int x, int y, int x2, int y2, int color)
        {
            fsr.sendByte((byte)SPE.DRAWRECTANGLE_1);
            fsr.sendByte((byte)SPE.DRAWRECTANGLE_2);

            fsr.sendByte((byte)(x >> 8));
            fsr.sendByte((byte)(x & 0xFF));
            fsr.sendByte((byte)(y >> 8));
            fsr.sendByte((byte)(y & 0xFF));
            fsr.sendByte((byte)(x2 >> 8));
            fsr.sendByte((byte)(x2 & 0xFF));
            fsr.sendByte((byte)(y2 >> 8));
            fsr.sendByte((byte)(y2 & 0xFF));
            fsr.sendByte((byte)(color >> 8));
            fsr.sendByte((byte)(color & 0xFF));

            return fsr.sendAndGetACK();
        }

        public int DrawFilledRectangle(int x, int y, int x2, int y2, int color)
        {
            fsr.sendByte((byte)SPE.DRAWFILLEDRECTANGLE_1);
            fsr.sendByte((byte)SPE.DRAWFILLEDRECTANGLE_2);

            fsr.sendByte((byte)(x >> 8));
            fsr.sendByte((byte)(x & 0xFF));
            fsr.sendByte((byte)(y >> 8));
            fsr.sendByte((byte)(y & 0xFF));
            fsr.sendByte((byte)(x2 >> 8));
            fsr.sendByte((byte)(x2 & 0xFF));
            fsr.sendByte((byte)(y2 >> 8));
            fsr.sendByte((byte)(y2 & 0xFF));
            fsr.sendByte((byte)(color >> 8));
            fsr.sendByte((byte)(color & 0xFF));

            return fsr.sendAndGetACK();
        }

        public int DrawFilledPolygon(int n, Point[] points, int color)
        {
#if PICASO
            fsr.sendByte((byte)SPE.DRAWFILLEDPOLYGON_1);
            fsr.sendByte((byte)SPE.DRAWFILLEDPOLYGON_2);

            fsr.sendByte((byte)(n >> 8));
            fsr.sendByte((byte)(n & 0xFF));

            for (int i = 0; i < n; i++)
            {
                fsr.sendByte((byte)(points[i].x >> 8));
                fsr.sendByte((byte)(points[i].x & 0xFF));
                fsr.sendByte((byte)(points[i].y >> 8));
                fsr.sendByte((byte)(points[i].y & 0xFF));
            }

            fsr.sendByte((byte)(color >> 8));
            fsr.sendByte((byte)(color & 0xFF));

            return fsr.sendAndGetACK();
#else
            return (int)FOURD.NAK;
#endif
        }

        public int DrawFilledTriangle(int x, int y, int x2, int y2,int x3, int y3, int color)
        {
#if PICASO
            fsr.sendByte((byte)SPE.DRAWFILLEDTRIANGLE_1);
            fsr.sendByte((byte)SPE.DRAWFILLEDTRIANGLE_2);

            fsr.sendByte((byte)(x >> 8));
            fsr.sendByte((byte)(x & 0xFF));
            fsr.sendByte((byte)(y >> 8));
            fsr.sendByte((byte)(y & 0xFF));
            fsr.sendByte((byte)(x2 >> 8));
            fsr.sendByte((byte)(x2 & 0xFF));
            fsr.sendByte((byte)(y2 >> 8));
            fsr.sendByte((byte)(y2 & 0xFF));
            fsr.sendByte((byte)(x3 >> 8));
            fsr.sendByte((byte)(x3 & 0xFF));
            fsr.sendByte((byte)(y3 >> 8));
            fsr.sendByte((byte)(y3 & 0xFF));
            fsr.sendByte((byte)(color >> 8));
            fsr.sendByte((byte)(color & 0xFF));

            return fsr.sendAndGetACK();
#else
            return (int)FOURD.NAK;
#endif
        }

        public int MoveOrigin(int x, int y)
        {
            fsr.sendByte((byte)SPE.MOVEORIGIN_1);
            fsr.sendByte((byte)SPE.MOVEORIGIN_2);

            fsr.sendByte((byte)(x >> 8));
            fsr.sendByte((byte)(x & 0xFF));
            fsr.sendByte((byte)(y >> 8));
            fsr.sendByte((byte)(y & 0xFF));

            return fsr.sendAndGetACK();
        }

        public int DrawButton(int state, int x, int y, int color, int txtcolor, int font,int txtwidth, int txtheight, string text)
        {
#if PICASO
            fsr.sendByte((byte)SPE.DRAWBUTTON_1);
            fsr.sendByte((byte)SPE.DRAWBUTTON_2);

            fsr.sendByte((byte)(state >> 8));
            fsr.sendByte((byte)(state & 0xFF));
            fsr.sendByte((byte)(x >> 8));
            fsr.sendByte((byte)(x & 0xFF));
            fsr.sendByte((byte)(y >> 8));
            fsr.sendByte((byte)(y & 0xFF));
            fsr.sendByte((byte)(color >> 8));
            fsr.sendByte((byte)(color & 0xFF));
            fsr.sendByte((byte)(txtcolor >> 8));
            fsr.sendByte((byte)(txtcolor & 0xFF));
            fsr.sendByte((byte)(font >> 8));
            fsr.sendByte((byte)(font & 0xFF));
            fsr.sendByte((byte)(txtwidth >> 8));
            fsr.sendByte((byte)(txtwidth & 0xFF));
            fsr.sendByte((byte)(txtheight >> 8));
            fsr.sendByte((byte)(txtheight & 0xFF));

            byte[] textBytes = Encoding.UTF8.GetBytes(text);
            foreach (byte bt in textBytes)
            {
                fsr.sendByte(bt);
            }

            fsr.sendByte(0x00);

            return fsr.sendAndGetACK();
#else
            return (int)FOURD.NAK;
#endif
        }

        public int DrawPanel(int state, int x, int y, int w, int h, int color)
        {
#if PICASO
            fsr.sendByte((byte)SPE.DRAWPANEL_1);
            fsr.sendByte((byte)SPE.DRAWPANEL_2);

            fsr.sendByte((byte)(state >> 8));
            fsr.sendByte((byte)(state & 0xFF));
            fsr.sendByte((byte)(x >> 8));
            fsr.sendByte((byte)(x & 0xFF));
            fsr.sendByte((byte)(y >> 8));
            fsr.sendByte((byte)(y & 0xFF));
            fsr.sendByte((byte)(w >> 8));
            fsr.sendByte((byte)(w & 0xFF));
            fsr.sendByte((byte)(h >> 8));
            fsr.sendByte((byte)(h & 0xFF));
            fsr.sendByte((byte)(color >> 8));
            fsr.sendByte((byte)(color & 0xFF));

            return fsr.sendAndGetACK();
#else
            return (int)FOURD.NAK;
#endif
        }

        public int ScreenCopyPaste(int xs, int ys, int xd, int yd,int width,int height)
        {
#if PICASO
            fsr.sendByte((byte)SPE.SCREENCOPYPASTE_1);
            fsr.sendByte((byte)SPE.SCREENCOPYPASTE_2);

            fsr.sendByte((byte)(xs >> 8));
            fsr.sendByte((byte)(xs & 0xFF));
            fsr.sendByte((byte)(ys >> 8));
            fsr.sendByte((byte)(ys & 0xFF));
            fsr.sendByte((byte)(xd >> 8));
            fsr.sendByte((byte)(xd & 0xFF));
            fsr.sendByte((byte)(yd >> 8));
            fsr.sendByte((byte)(yd & 0xFF));
            fsr.sendByte((byte)(width >> 8));
            fsr.sendByte((byte)(width & 0xFF));
            fsr.sendByte((byte)(height >> 8));
            fsr.sendByte((byte)(height & 0xFF));

            return fsr.sendAndGetACK();
#else
            return (int)FOURD.NAK;
#endif
        }
        #endregion

        #region Media

        public int MediaInit()
        {
            fsr.sendByte((byte)SPE.MEDIAINIT_1);
            fsr.sendByte((byte)SPE.MEDIAINIT_2);

            return fsr.getResponse();
        }

        public int SetByteAddress(int hi, int lo)
        {
            fsr.sendByte((byte)SPE.SETBYTEADDRESS_1);
            fsr.sendByte((byte)SPE.SETBYTEADDRESS_2);
            fsr.sendByte((byte)(hi >> 8));
            fsr.sendByte((byte)(hi & 0xFF));
            fsr.sendByte((byte)(lo >> 8));
            fsr.sendByte((byte)(lo & 0xFF));

            return fsr.sendAndGetACK();
        }

        public int DisplayImageRAW(int x, int y)
        {
            fsr.sendByte((byte)SPE.DISPLAYIMAGERAW_1);
            fsr.sendByte((byte)SPE.DISPLAYIMAGERAW_2);
            fsr.sendByte((byte)(x >> 8));
            fsr.sendByte((byte)(x & 0xFF));
            fsr.sendByte((byte)(y >> 8));
            fsr.sendByte((byte)(y & 0xFF));

            return fsr.sendAndGetACK();
        }

        public int DisplayVideoRAW(int x, int y)
        {
            fsr.sendByte((byte)SPE.DISPLAYVIDEORAW_1);
            fsr.sendByte((byte)SPE.DISPLAYVIDEORAW_2);
            fsr.sendByte((byte)(x >> 8));
            fsr.sendByte((byte)(x & 0xFF));
            fsr.sendByte((byte)(y >> 8));
            fsr.sendByte((byte)(y & 0xFF));

            return fsr.sendAndGetACK();
        }

        public int DisplayVideoFrameRAW(int x, int y,int frame)
        {
            fsr.sendByte((byte)SPE.DISPLAYVIDEOFRAMERAW_1);
            fsr.sendByte((byte)SPE.DISPLAYVIDEOFRAMERAW_2);
            fsr.sendByte((byte)(x >> 8));
            fsr.sendByte((byte)(x & 0xFF));
            fsr.sendByte((byte)(y >> 8));
            fsr.sendByte((byte)(y & 0xFF));
            fsr.sendByte((byte)(frame >> 8));
            fsr.sendByte((byte)(frame & 0xFF));

            return fsr.sendAndGetACK();
        }

        #endregion

        #region Serial

        public int SetBaudRate(int mode, int rate)
        {
            fsr.sendByte((byte)SPE.SETBAUDRATE_1);
            fsr.sendByte((byte)SPE.SETBAUDRATE_2);
            fsr.sendByte((byte)(mode >> 8));
            fsr.sendByte((byte)(mode & 0xFF));

            fsr.send();

            ChangeBaudRate(rate);

            return fsr.getACK();
        }

        #endregion

#if PICASO

        #region FAT16

        public int LoadImageControl(string filename1, string filename2, int mode)
        {
            fsr.sendByte((byte)SPE.LOADIMAGECONTROL_1);
            fsr.sendByte((byte)SPE.LOADIMAGECONTROL_2);

            byte[] textBytes = Encoding.UTF8.GetBytes(filename1);
            foreach (byte bt in textBytes)
            {
                fsr.sendByte(bt);
            }

            textBytes = Encoding.UTF8.GetBytes(filename2);
            foreach (byte bt in textBytes)
            {
                fsr.sendByte(bt);
            }

            return fsr.getResponse();
        }

        public int FileMount()
        {
            fsr.sendByte((byte)SPE.FILEMOUNT_1);
            fsr.sendByte((byte)SPE.FILEMOUNT_2);

            return fsr.getResponse();
        }

        #endregion

        #region TouchScreen

        public int TouchDetectRegion(int x1, int y1, int x2, int y2)
        {
            fsr.sendByte((byte)SPE.TOUCHDETECTREGION_1);
            fsr.sendByte((byte)SPE.TOUCHDETECTREGION_2);
            fsr.sendByte((byte)(x1 >> 8));
            fsr.sendByte((byte)(x1 & 0xFF));
            fsr.sendByte((byte)(y1 >> 8));
            fsr.sendByte((byte)(y1 & 0xFF));
            fsr.sendByte((byte)(x2 >> 8));
            fsr.sendByte((byte)(x2 & 0xFF));
            fsr.sendByte((byte)(y2 >> 8));
            fsr.sendByte((byte)(y2 & 0xFF));

            return fsr.sendAndGetACK();
        }

        public int TouchSet(int mode)
        {
            fsr.sendByte((byte)SPE.TOUCHSET_1);
            fsr.sendByte((byte)SPE.TOUCHSET_2);
            fsr.sendByte((byte)(mode >> 8));
            fsr.sendByte((byte)(mode & 0xFF));

            return fsr.sendAndGetACK();
        }

        public int TouchGet(int mode)
        {
            fsr.sendByte((byte)SPE.TOUCHGET_1);
            fsr.sendByte((byte)SPE.TOUCHGET_2);
            fsr.sendByte((byte)(mode >> 8));
            fsr.sendByte((byte)(mode & 0xFF));

            return fsr.getResponse();
        }

        #endregion

        #region Touch Custom

        public Point lastTouchPoint = new Point(0,0);
        public long lastTouchUpdate;
        public bool isTouchDown = false;

        public Point TouchScan()
        {
            long now = DateTime.Now.Ticks / 10000;
            if (now - lastTouchUpdate >= (int)SPE.TOUCHRATE)
            {
                lastTouchUpdate = DateTime.Now.Ticks / 10000;

                int status = TouchGetStatus();
                switch (status)
                {
                    case (int)SPE.TOUCHNOTOUCH:
                        if (!isTouchDown)
                        {
                            return null;
                        }
                        break;
                    case (int)SPE.TOUCHPRESS:
                        lastTouchPoint.x = TouchGetX();
                        lastTouchPoint.y = TouchGetY();
                        isTouchDown = true;
                        if (TouchDownEvent != null) TouchDownEvent(new object(), new TouchEventArgs(lastTouchPoint.x, lastTouchPoint.y));
                        break;
                    case (int)SPE.TOUCHMOVING:
                        lastTouchPoint.x = TouchGetX();
                        lastTouchPoint.y = TouchGetY();
                        isTouchDown = true;
                        if (TouchMoveEvent != null) TouchMoveEvent(new object(), new TouchEventArgs(lastTouchPoint.x, lastTouchPoint.y));
                        break;
                    case (int)SPE.TOUCHRELEASE:
                        lastTouchPoint.x = TouchGetX();
                        lastTouchPoint.y = TouchGetY();
                        isTouchDown = false;
                        if (TouchUpEvent != null) TouchUpEvent(new object(), new TouchEventArgs(lastTouchPoint.x, lastTouchPoint.y));
                        break;
                }
            }

            return lastTouchPoint;
        }

        public void TouchEnable()
        {
            TouchSet((int)SPE.TOUCHSETINIT);
        }

        public void TouchReset()
        {
            TouchSet((int)SPE.TOUCHSETRESETREGION);
        }

        public void TouchDisable()
        {
            TouchSet((int)SPE.TOUCHSETDISABLE);
        }

        public int TouchGetStatus()
        {
            return TouchGet((int)SPE.TOUCHGETSTATUS);
        }

        public int TouchGetX()
        {
            return TouchGet((int)SPE.TOUCHGETX);
        }

        public int TouchGetY()
        {
            return TouchGet((int)SPE.TOUCHGETY);
        }

        #endregion

#endif

        #region Image Control

#if PICASO
        public int ShowImage(int handle,int index)
        {
            fsr.sendByte((byte)SPE.SHOWIMAGE_1);
            fsr.sendByte((byte)SPE.SHOWIMAGE_2);

            fsr.sendByte((byte)(handle >> 8));
            fsr.sendByte((byte)(handle & 0xFF));
            fsr.sendByte((byte)(index >> 8));
            fsr.sendByte((byte)(index & 0xFF));

            return fsr.getResponse();
        }
#endif

        #endregion

        #region Custom

        public void GradientY(int sr, int sg, int sb, int er, int eg, int eb, int w, int h,int step)
        {
            int y = 0;
            float incr = (float)(er - sr) / (h / step);
            float incg = (float)(eg - sg) / (h / step);
            float incb = (float)(eb - sb) / (h / step);

            float cr = sr;
            float cg = sg;
            float cb = sb;

            for (y = 0; y < h; y+=step)
            {
                cr += incr;
                cg += incg;
                cb += incb;

                DrawFilledRectangle(0, y, w, y + step, ColorExtensions.RGB16((int)cr, (int)cg, (int)cb));
            }
        }

        #endregion
    }
}
